package mylab.io.core.codec;

import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import lombok.extern.slf4j.Slf4j;
import mylab.io.core.event.ChannelExceptionEvent;
import mylab.utils.common.guava.AsyncEventUtil;

@Slf4j
@ChannelHandler.Sharable
public class ExceptionHandler extends ChannelDuplexHandler {
    public static final String HANDLER_NAME = ExceptionHandler.class.getSimpleName();

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ctx.write(msg, promise.addListener((ChannelFutureListener) future -> {
            if (!future.isSuccess()) {
                onException(ctx, future.cause(), false);
            }
        }));
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        onException(ctx, cause, true);
    }

    private void onException(ChannelHandlerContext ctx, Throwable cause, boolean isInbound) {
        log.error("{} 时发生异常：{}", isInbound ? "入站" : "出站", cause.getMessage());
        cause.printStackTrace();
        AsyncEventUtil.postEvent(new ChannelExceptionEvent(ctx, new ChannelExceptionEvent.ChannelException(isInbound, cause)));
    }
}
